<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <title>Title</title>
    <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" />
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        body,
        html {
            width: 100%;
            height: 100%;
            font-family: Arial, sans-serif;
        }

        /* 去掉logo */
        .amap-logo {
            display: none;
            opacity: 0 !important;
        }

        /* 去掉版本号 */
        .amap-copyright {
            opacity: 0;
        }

        #container {
            width: calc(100% - 180px);
            height: calc(100% - 50px);
            position: absolute;
            top: 50px;
            left: 180px;
        }

        #topbar {
            width: 100%;
            height: 50px;
            background-color: #333;
            color: white;
            display: flex;
            align-items: center;
            justify-content: space-between;
            padding: 0 10px 0 24px;
            position: fixed;
            top: 0;
            left: 0;
            z-index: 2;
        }

        #topbar button {
            background-color: rgba(0, 0, 0, 0.2);
            color: azure;
            text-decoration: none;
            padding: 6px 15px;
            margin: 3px 3px;
            cursor: pointer;
        }

        #topbar button:hover {
            color: rgb(0, 136, 255);
        }

        #sidebar {
            width: 180px;
            height: 100%;
            background-color: #444;
            position: fixed;
            top: 50px;
            left: 0;
            z-index: 2;
        }

        #sidebar ul {
            list-style: none;
        }

        #sidebar ul li {
            display: flex;
            align-items: center;
            justify-content: center;
            flex-direction: column;
        }

        #sidebar ul li a {
            color: white;
            text-decoration: none;
            display: block;
            font-size: 12px;
            cursor: pointer;
            margin: 5px;
        }

        #sidebar button {
            background-color: #444;
            color: aliceblue;
            width: 100%;
            height: 36px;
            font-size: 15px;
        }

        #sidebar ul li button:hover {
            background-color: #222;
            font-size: 18px;
            color: rgb(0, 136, 255);
        }

        #route1-submenu,
        #route2-submenu {
            display: none;
        }

        #route1-submenu a:hover,
        #route2-submenu a:hover {
            font-size: 15px;
            color: rgb(0, 136, 255);
        }
    </style>
</head>

<body>
    <div id="topbar">
        <h2>安 防 巡 检 系 统</h2>
        <div>
            <button id='add-route' onclick="toggleAddRoute()">添加路线</button>
            <button id='plan-route' onclick="planAndGenerateRoute()">路线规划</button>
            <button id='clear' onclick="carGo()">路线演示</button>
            <button id='save-route'>保存路线</button>
            <button id='clear' onclick="clearMarker()">清空标点</button>
        </div>
    </div>
    <div id="sidebar">
        <ul>
            <li>
                <button onclick="toggleRoute1Submenu()">线 路 一</button>
                <ul id="route1-submenu">
                    <li><a onclick="highlightPoint(0)">标点1</a></li>
                    <li><a onclick="highlightPoint(1)">标点2</a></li>
                    <li><a onclick="highlightPoint(2)">标点3</a></li>
                    <li><a onclick="highlightPoint(3)">标点4</a></li>
                    <li><a onclick="highlightPoint(4)">标点5</a></li>
                </ul>
                <button onclick="toggleRoute2Submenu()">线 路 二</button>
                <ul id="route2-submenu">
                    <li><a onclick="highlightPoint(0)">标点1</a></li>
                    <li><a onclick="highlightPoint(1)">标点2</a></li>
                    <li><a onclick="highlightPoint(2)">标点3</a></li>
                    <li><a onclick="highlightPoint(3)">标点4</a></li>
                </ul>
            </li>
        </ul>
    </div>
    <div id="container"></div>
    <script type="text/javascript">
        window._AMapSecurityConfig = {
            securityJsCode: '9dd84acdf934980b087d2fc7170d4274',
        }
    </script>
    <script type="text/javascript"
        src="https://webapi.amap.com/maps?v=1.4.15&key=3d5b54830455c348e82733f15b8cb9e9"></script>
    <script>
        let center = [120.759976, 30.125826]; // 中心点坐标

        // 设置主视图
        var map = new AMap.Map('container', {
            zoom: 16, // 级别
            viewMode: '3D',
            pitch: 45,
            center, // 中心点坐标
        });

        AMap.plugin([
            'AMap.ToolBar',
            'AMap.Scale',
            'AMap.OverView',
            'AMap.MapType',
            'AMap.Geolocation',
        ], function () {
            // 在图面添加工具条控件，工具条控件集成了缩放、平移、定位等功能按钮在内的组合控件
            map.addControl(new AMap.ToolBar());

            // 在图面添加比例尺控件，展示地图在当前层级和纬度下的比例尺
            map.addControl(new AMap.Scale());

            // 在图面添加鹰眼控件，在地图右下角显示地图的缩略图
            map.addControl(new AMap.OverView({ isOpen: true }));

            // 在图面添加类别切换控件，实现默认图层与卫星图、实施交通图层之间切换的控制
            map.addControl(new AMap.MapType());

            // 在图面添加定位控件，用来获取和展示用户主机所在的经纬度位置
            // map.addControl(new AMap.Geolocation());
        });

        let markers = []; // 用来存放点标注
        let info = []; // 用来保存点击标注产生的信息窗口
        let geojson = new AMap.GeoJSON({
            geojson: null,
        });
        let addingRoute = false;
        let carPath = []; // 小车行驶路线-坐标点

        //点击地图生成点标记
        const areaPath = [
            [120.742286, 30.147283],
            [120.783449, 30.1388],
            [120.796235, 30.140656],
            [120.797418, 30.130771],
            [120.78069, 30.130658],
            [120.782091, 30.125128],
            [120.788647, 30.124749],
            [120.789129, 30.121946],
            [120.803947, 30.122331],
            [120.803816, 30.120513],
            [120.806749, 30.110778],
            [120.805786, 30.107028],
            [120.799524, 30.107444],
            [120.799218, 30.105512],
            [120.799918, 30.102519],
            [120.798517, 30.099564],
            [120.798254, 30.097519],
            [120.79948, 30.096117],
            [120.798254, 30.093465],
            [120.798386, 30.08475],
            [120.800444, 30.083803],
            [120.805217, 30.082931],
            [120.806706, 30.080999],
            [120.799042, 30.078763],
            [120.784022, 30.086834],
            [120.772768, 30.093162],
            [120.768871, 30.096458],
            [120.764098, 30.096306],
            [120.762215, 30.091495],
            [120.762696, 30.088085],
            [120.763353, 30.08187],
            [120.758799, 30.081643],
            [120.741108, 30.084902],
            [120.707994, 30.087125],
            [120.681932, 30.098463],
            [120.670251, 30.107925],
            [120.681796, 30.120861],
            [120.688382, 30.122335],
            [120.693341, 30.120995],
            [120.693031, 30.112081],
            [120.692566, 30.108528],
            [120.700547, 30.111947],
            [120.708218, 30.111813],
            [120.714107, 30.116689],
            [120.721081, 30.131401],
            [120.738205, 30.131535],
            [120.75037, 30.132205]
        ];
        // 创建区域
        const area = new AMap.Polygon({
            path: areaPath,
            fillColor: '#ADD8E6', // 填充颜色
            borderColor: '#5ABAD7', // 线颜色
            strokeWeight: 3, // 线宽
            fillOpacity: 0.3, // 填充透明度
            bubble: true // 是否将覆盖物的鼠标或touch等事件冒泡到地图上
        });
        map.add(area);

        // 添加路线 判断
        function toggleAddRoute() {
            addingRoute = !addingRoute;
            if (addingRoute) {
                map.on('click', addMarker);
                alert("您现在可以在地图上添加标点");
            } else {
                map.off('click', addMarker);
                alert("添加标点已结束");
            }
        }

        // 添加点标记
        function addMarker(e) {
            // 检查点击位置是否在规划区域内
            if (area.contains(e.lnglat)) {
                let marker = new AMap.Marker({
                    draggable: true,
                    position: e.lnglat, // 位置
                    extData: { // 自定义属性
                        _geoJsonProperties: {
                            id: markers.length + 1, /*点标记的唯一识别码*/
                            click: 0, /*点标记的点击次数*/
                        },
                    },
                });
                markers.push(marker); // 创建一个点就加进去
                console.log(marker.getPosition());
                geojson.addOverlay(marker); /*将一个点标记放到geojson中转站中*/
                saveData(geojson.toGeoJSON()); /*将geojson中转站内的标记全部保存到标准geoJSON数据*/
                console.log('geojson:', geojson.toGeoJSON());
                //点击点标记显示打卡次数
                marker.on('click', function (e) { /*点击事件*/
                    let i = ++marker.getExtData()._geoJsonProperties.click; /*在某标签上点击一次对应的click加一次*/
                    info = new AMap.InfoWindow({
                        anchor: 'top-center',
                        content: `<div>${markers.indexOf(marker) + 1}打卡了${i}次</div>`
                    });
                    info.open(map, marker.getPosition());
                    saveData(geojson.toGeoJSON()); /*将geojson中转站内的标记全部保存到标准geoJSON数据*/
                });
            } else {
                alert("点标记必须在规划区域范围内！");
            }


        }

        // 路线规划
        function planAndGenerateRoute() {
            let opts = {
                waypoints: [],
            };

            // 固定起点，终点方案
            let start = center;
            let end = center;

            // 自定义起点，终点方案
            // let start = [];
            // let end = [];

            geojson.eachOverlay(function (item) {
                //遍历geojson得到每一个点的坐标
                opts.waypoints.push(item.getPosition());
            });

            // 固定起点，终点方案
            if (opts.waypoints.length === 0) {
                alert("请先添加标点！");
                return;
            }

            // 自定义起点，终点方案
            // start = opts.waypoints.shift(); //删除数组最前面的对象，且返回该对象作为起点
            // end = opts.waypoints.pop(); //删除数组最后面的对象，且返回该对象作为终点

            // 自定义起点，终点方案
            /* if (start.length === 0) {
                alert("请先添加标点！");
                return;
            } */

            //调用高德路线规划插件
            AMap.plugin('AMap.Driving', function () {
                let driving = new AMap.Driving({
                    map: map,
                    //驾车测策
                    policy: AMap.DrivingPolicy.LEAST_TIME,
                });
                //设置规划路线方法，参数分别为起点，终点，中途点

                carPath = []; // 清空数据，方便重新规划
                // 获取驾车路线数据：
                driving.search(start, end, opts, function (status, result) {
                    if (status === 'complete') {
                        console.log("点标记-坐标：", result);
                        result.routes[0].steps.forEach(item => {
                            console.log("小车路线-坐标：", item);
                            let end = [item.start_location.lng, item.start_location.lat];
                            carPath.push(end);
                        });

                        // 设置小车路线的样式
                        var passedPolyline = new AMap.Polyline({
                            map: map,
                            path: center,
                            strokeColor: "#AF5", //线颜色
                            strokeWeight: 6, //线宽
                        });

                    } else {
                        console.log('获取驾车路线数据失败：' + result);
                    }
                });

            });
            console.log(markers);
        }

        // 清除点标记
        function clearMarker() {
            geojson = new AMap.GeoJSON(); //中转站清空，这样下次新生成的点标注就不会把之前中转站的旧数据存入JSON中
            map.remove(markers); //移除所有标记
            markers = []; //将数组清空
            map.remove(info); //打卡信息框删除
            localStorage.clear(); /*清除所有已经保存的JSON字符串*/
            location.reload();
        }

        map.add(geojson);
        if (JSON.stringify(getData()) != '[]') {
            //导入数据
            geojson.importData(getData());
            //恢复旧数据的点击事件
            geojson.eachOverlay(function (item) {
                item.on('click', function (e) {
                    let i = ++item.getExtData()._geoJsonProperties.click; /*在某标签上点击一次对应的click加一次*/
                    let info = new AMap.InfoWindow({
                        anchor: 'top-center',
                        content: `<div>${markers.indexOf(marker) + 1}打卡了${i}次</div>`
                    });
                    info.open(map, item.getPosition());
                    saveData(geojson.toGeoJSON()); /*将点标签内的新属性转换到标准geoJSON数据*/
                });
            });
        }

        //存储数据
        function saveData(geoJSON) {
            localStorage.setItem('data', JSON.stringify(geoJSON));
        }

        //提取数据
        function getData() {
            return JSON.parse(localStorage.getItem('data'));
        }

        // 安防路线 显示
        function getSecurityRoute(points) {
            points.forEach((point, index) => {
                let marker = new AMap.Marker({
                    position: point,
                    // offset: new AMap.Pixel(-13, -30), // 点位偏移
                    extData: {
                        _geoJsonProperties: {
                            id: markers.length + index + 1,
                            click: 0,
                        },
                    },
                });
                markers.push(marker); // 将标记添加到 markers 数组
                geojson.addOverlay(marker); // 将标记添加到 geojson 对象
                map.add(marker); // 将标记添加到地图
            });

            saveData(geojson.toGeoJSON()); // 保存标记数据到本地存储
        }

        // 点标记信息窗体显示
        function getInfoWindow(checkMark) {
            var infoWindow = new AMap.InfoWindow({
                anchor: "top-left",
                content: "这是信息窗体！",
            });

            infoWindow.open(map, checkMark);
        }

        // 路线子菜单显示/隐藏
        function toggleRoute1Submenu() { // 路线一
            let submenu = document.getElementById('route1-submenu');
            submenu.style.display = (submenu.style.display === 'none' || submenu.style.display === '') ? 'block' : 'none';
            // 安防路线
            let securityRoute1 = [
                [120.754284, 30.142401],
                [120.764407, 30.122092],
                [120.764772, 30.125532],
                [120.764361, 30.122052],
                [120.758645, 30.114418],
            ];
            getSecurityRoute(securityRoute1);
            planAndGenerateRoute() // 调用路线规划
        }
        function toggleRoute2Submenu() { // 路线二
            let submenu = document.getElementById('route2-submenu');
            submenu.style.display = (submenu.style.display === 'none' || submenu.style.display === '') ? 'block' : 'none';
            // 安防路线
            let securityRoute2 = [
                [120.757901, 30.128186],
                [120.761785, 30.123899],
                [120.770347, 30.12518],
                [120.769209, 30.128279]
            ];
            getSecurityRoute(securityRoute2);
            planAndGenerateRoute() // 调用路线规划
        }

        // 高亮显示指定的标点
        function highlightPoint(index) {
            let marker = markers[index];
            if (marker) {
                let checkMark = [marker.De.position.lng, marker.De.position.lat]
                console.log('选中点标记：', checkMark)
                map.setCenter(marker.getPosition());
                marker.setAnimation('AMAP_ANIMATION_BOUNCE');
                setTimeout(() => marker.setAnimation(null), 2000);
                getInfoWindow(checkMark)
            }
        }

        //动态控制小车移动速度
        window.speed = 20
        // 小车
        var carmarker = new AMap.Marker({
            map: map,
            position: [120.759976, 30.125826], // 小车初始位置
            icon: "https://webapi.amap.com/images/car.png",
            //点标记显示位置偏移量，默认值为Pixel(-10,-34)。 因为图片都是矩形的 放到地图上可能位置不太对 通过这个属性 可以调一调位置
            offset: new AMap.Pixel(-26, -13),
            //是否自动旋转  点标记在使用moveAlong动画时，路径方向若有变化，点标记是否自动调整角度，默认为false。广泛用于自动调节车辆行驶方向。
            autoRotation: true,
            //点标记的旋转角度，广泛用于改变车辆行驶方向
            // 因为图片 可能方向不太对  通过这个旋转一下图片，但是这个不要和autoRotation 混淆了哦， 这个angle是图片刚加载出来之后的旋转角度，autoRotation是在angle基础上进行旋转哦
            angle: -90,
        });
        map.setFitView();
        function carGo() {
            // 第一个参数标识这个标记 移动的路径， 第二个是移动的速度
            //第三个参数 是变化曲线函数 可以动态控制 移动速度
            carmarker.moveAlong(carPath, 200, function (e) {
                // e 是 当前小汽车 在路径中的比值
                // 路径是由多个坐标组成, e 不是整个路径的比值
                // e 是每两个坐标点之间的比值 从0 到 1
                // return 返回的值 就是改变小汽车在路径上的比值 ,比如现在走了一半(e为0.5),这时候return 0.8 那小车就会移动到 0.8的位置上,视觉上小车移动速度就变快了,但是不能超过1 超过1 就 跑出路径了
                return e * window.speed > 1 ? 1 : e * window.speed
            });
        }
    </script>
</body>

</html>